package com.zmn.oms.business.impl.servtype;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.zmn.base.price.common.dro.item.ItemAdditionDRO;
import com.zmn.base.price.common.dto.TariffTypeDRO;
import com.zmn.base.price.common.dto.TariffTypeQuery;
import com.zmn.base.price.dubbo.interfaces.calculate.ProductTariffRemoteService;
import com.zmn.base.price.dubbo.interfaces.item.ItemAdditionRemoteService;
import com.zmn.base.product.common.consts.BaseProductConsts;
import com.zmn.base.product.common.dto.product.ProductBaseQuery;
import com.zmn.base.product.common.dto.product.ec.ProductBaseDRO;
import com.zmn.base.product.dubbo.interfaces.product.foreign.ProductForeignListRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.oms.business.interfaces.servtype.ServItemBService;
import com.zmn.oms.business.interfaces.yeyxplus.YeyxPlusBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.dio.quotation3.ArtificialPromDRO;
import com.zmn.oms.common.dio.quotation3.ArtificialPromListQuery;
import com.zmn.oms.common.enums.ServiceItemTypeEnum;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.dto.work.modify.*;
import com.zmn.oms.model.entity.masterworking.MasterWorking;
import com.zmn.oms.model.entity.product.OrderProduct;
import com.zmn.oms.model.entity.serviceitem.OrderServiceItem;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.services.interfaces.masterworking.MasterWorkingService;
import com.zmn.oms.services.interfaces.product.OrderProductService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.scm2.common.model.dro.BasePageDRO;
import com.zmn.scm2.common.model.dro.scm.engineer.warehouse.EngineerWarehouseDRO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.curator.shaded.com.google.common.collect.Lists;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Primary
@Service
@Slf4j
public class ServItemBServiceImpl implements ServItemBService {

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private ProductTariffRemoteService productTariffRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private ProductForeignListRemoteService productForeignListRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    protected ItemAdditionRemoteService itemAdditionRemoteService;

    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private OrderProductService orderProductService;
    @Autowired
    private MasterWorkingService masterWorkingService;
    @Autowired
    private YeyxPlusBService yeyxPlusBService;

    /**
     * 获取服务
     * @param servType
     * @return
     */
    private ServItemBService getService(Integer servType) {
        return ServItemTemplateFactory.getTemplateService(servType);
    }

    @Override
    public ResponseDTO<ServiceItemResultDTO> getServiceItem(ServiceItemQueryDTO serviceItemQueryDTO) {
        return getService(serviceItemQueryDTO.getServItemType()).getServiceItem(serviceItemQueryDTO);
    }

    @Override
    public List<ServiceItemResultDTO> listServiceItem(ServiceItemQueryDTO serviceItemQueryDTO) {
        return getService(serviceItemQueryDTO.getServItemType()).listServiceItem(serviceItemQueryDTO);
    }

    @Override
    public ResponseDTO<BasePageDRO<EngineerWarehouseDRO>> listPageEngineerWarehouseByQueryV2(PartQueryDTO partQueryDTO) throws OmsBaseException {
        return getService(partQueryDTO.getServItemType()).listPageEngineerWarehouseByQueryV2(partQueryDTO);
    }

    @Override
    public Integer getServItemType(CheckQuotationTypeOrderDTO checkQuotationTypeOrderDTO) {
        log.info("ServTypeDistributeServiceImpl.getServItemType checkQuotationTypeOrderDTO={}", checkQuotationTypeOrderDTO);
        // 退款单或返修单或赔偿单，不参与计价
        if (Objects.equals(checkQuotationTypeOrderDTO.getType(), OrderConsts.ORDER_TYPE_REWORK)
                || Objects.equals(checkQuotationTypeOrderDTO.getType(), OrderConsts.ORDER_TYPE_REFUND)
                || Objects.equals(checkQuotationTypeOrderDTO.getType(), OrderConsts.ORDER_TYPE_COMPENSATE)) {
            return OrderConsts.SERVICE_ITEM_TYPE_ORDER;
        }

        // 啄木鸟,川南环保 以外的其他服务平台，不参与计价
        if (NumberUtil.isNotNullOrZero(checkQuotationTypeOrderDTO.getPlatWork()) && !Objects.equals(checkQuotationTypeOrderDTO.getPlatWork(), GlobalConsts.PLAT_MARK_ZMN)) {
            return OrderConsts.SERVICE_ITEM_TYPE_ORDER;
        }

        // 厂商单，不参与计价
        if (NumberUtil.isNotNullOrZero(checkQuotationTypeOrderDTO.getSourceType()) && Objects.equals(checkQuotationTypeOrderDTO.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_FACTORY)) {
            return OrderConsts.SERVICE_ITEM_TYPE_ORDER;
        }

        Integer productId = NumberUtil.isNotNullOrZero(checkQuotationTypeOrderDTO.getProductId()) ? checkQuotationTypeOrderDTO.getProductId() : checkQuotationTypeOrderDTO.getShowProductId();
        if (NumberUtil.isNullOrZero(productId)) {
            productId = checkQuotationTypeOrderDTO.getProductId();
        }

        List<Integer> productIdList = Lists.newArrayList(productId);
        Integer showType = null;
        try {
            Map<Integer, ProductBaseDRO> productBaseDROMap = this.getProductBaseDROMap(productIdList);
            ProductBaseDRO productBaseDRO = productBaseDROMap.get(productId);
            showType = productBaseDRO.getShowType();
        } catch (OmsBaseException e) {
            return OrderConsts.SERVICE_ITEM_TYPE_ORDER;
        }

        TariffTypeQuery tariffTypeQuery = TariffTypeQuery
                .builder()
                .bizType(checkQuotationTypeOrderDTO.getBizType())
                .channelId(checkQuotationTypeOrderDTO.getChannelId())
                .cityId(checkQuotationTypeOrderDTO.getCityId())
                .productIdList(Lists.newArrayList(productId))
                .maxType(checkQuotationTypeOrderDTO.getTariffType())
                .showType(showType)
                .build();
        log.info("查询产品优先支持的价格表入参：{}", JSON.toJSONString(tariffTypeQuery));
        ResponseDTO<List<TariffTypeDRO>> listResponseDTO = productTariffRemoteService.listTariffByQuery(tariffTypeQuery);
        log.info("查询产品优先支持的价格表出参：{}", JSON.toJSONString(listResponseDTO));

        if (!listResponseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(listResponseDTO.getData())) {
            return OrderConsts.SERVICE_ITEM_TYPE_ORDER;
        }

        Integer finalProductId = productId;
        TariffTypeDRO tariffTypeDRO = listResponseDTO.getData()
                .stream()
                .filter(e -> Objects.equals(e.getProductId(), finalProductId))
                .findAny()
                .orElse(null);
        if (Objects.isNull(tariffTypeDRO)) {
            return OrderConsts.SERVICE_ITEM_TYPE_ORDER;
        }
        if (NumberUtil.isNullOrZero(tariffTypeDRO.getTariffType())) {
            return OrderConsts.SERVICE_ITEM_TYPE_ORDER;
        }

        // 是否兼容一口价
        if (checkQuotationTypeOrderDTO.isCompatibilityFinalPrice()) {
            if (Objects.equals(tariffTypeDRO.getTariffType(), OrderConsts.SERVICE_ITEM_TYPE_FINAL_PRICE)) {
                tariffTypeDRO.setTariffType(OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE);
            }
        }

        // 计价器3.0/2.0判断新言而有信家修匠逻辑，如果家修匠师傅开通新言而有信试点，计价器3.0改为工单服务项
        if (Objects.equals(tariffTypeDRO.getTariffType(), OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE)
                || Objects.equals(tariffTypeDRO.getTariffType(), OrderConsts.SERVICE_ITEM_TYPE_FAULT)) {
            boolean isYeyxPilot = yeyxPlusBService.isYeyxPilot(checkQuotationTypeOrderDTO.getCompanyId(), checkQuotationTypeOrderDTO.getCityId(), checkQuotationTypeOrderDTO.getMasterId());

            // 不是言而有信试点直接返回
            if (!isYeyxPilot) {
                return tariffTypeDRO.getTariffType();
            }

            // 如果修改之前是计价器3.0/2.0，那么还是计价器3.0/2.0
            if (Objects.equals(checkQuotationTypeOrderDTO.getBeforeServItemType(), OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE) ||
                    Objects.equals(checkQuotationTypeOrderDTO.getBeforeServItemType(), OrderConsts.SERVICE_ITEM_TYPE_FAULT)) {
                return tariffTypeDRO.getTariffType();
            }

            return OrderConsts.SERVICE_ITEM_TYPE_ORDER;
        }

        return tariffTypeDRO.getTariffType();
    }

    @Override
    public boolean isQuotationType(Integer servType) {
        log.info("ServTypeDistributeServiceImpl.isQuotationType servType={}", servType);
        return Objects.equals(servType, OrderConsts.SERVICE_ITEM_TYPE_FAULT)
                || Objects.equals(servType, OrderConsts.SERVICE_ITEM_TYPE_ADVANCE_PAY)
                || Objects.equals(servType, OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE);
    }

    @Override
    public void processProductTaraiffId(ProductTaraiffIdDTO productTaraiffIdDTO) {
        log.info("ServTypeDistributeServiceImpl.processProductTaraiffId productTaraiffIdDTO={}", productTaraiffIdDTO);
        for (OrderProduct orderProduct : productTaraiffIdDTO.getOrderProductList()) {
            if (Objects.nonNull(orderProduct.getTariffId())) {
                continue;
            }
            Integer productType = NumberUtil.isNullOrZero(orderProduct.getProductId()) ? BaseProductConsts.EC_SHOW_TYPE : BaseProductConsts.ERP_SHOW_TYPE;

            TariffTypeQuery tariffTypeQuery = TariffTypeQuery
                    .builder()
                    .cityId(productTaraiffIdDTO.getCityId())
                    .channelId(productTaraiffIdDTO.getChannelId())
                    .bizType(productTaraiffIdDTO.getBizType())
                    .showType(productType)
                    .productIdList(Lists.newArrayList(NumberUtil.isNullOrZero(orderProduct.getProductId()) ? orderProduct.getShowProductId() : orderProduct.getProductId()))
                    .maxType(productTaraiffIdDTO.getTariffType())
                    .build();
            log.info("查询产品优先支持的价格表入参：{}", JSON.toJSONString(tariffTypeQuery));
            ResponseDTO<List<TariffTypeDRO>> listResponseDTO = productTariffRemoteService.listTariffByQuery(tariffTypeQuery);
            log.info("查询产品优先支持的价格表出参：{}", JSON.toJSONString(listResponseDTO));
            if (CollectionUtils.isEmpty(listResponseDTO.getData())) {
                continue;
            }
            orderProduct.setTariffId(listResponseDTO.getData().get(0).getTariffId());
        }
    }

    @Override
    public List<OrderServiceItem> filterServiceItem(List<OrderServiceItem> serviceItems, Integer servItemType, Integer finalPrice) {
        log.info("ServItemBServiceImpl.filterServiceItem servType={}", servItemType);
        return getService(servItemType).filterServiceItem(serviceItems, servItemType, finalPrice);
    }

    @Override
    public BackProductPriceResultDTO queryBackProductPrice(BackProductPriceQueryDTO backProductPriceQueryDTO) {
        log.info("ServItemBServiceImpl.queryBackProductPrice backProductPriceQueryDTO={}", JSON.toJSONString(backProductPriceQueryDTO));
        CheckQuotationTypeOrderDTO checkQuotationTypeOrderDTO = CheckQuotationTypeOrderDTO
                .builder()
                .platWork(backProductPriceQueryDTO.getPlatWork())
                .showProductId(backProductPriceQueryDTO.getShowProductId())
                .productId(backProductPriceQueryDTO.getProductId())
                .bizType(backProductPriceQueryDTO.getBizType())
                .channelId(backProductPriceQueryDTO.getChannelId())
                .cityId(backProductPriceQueryDTO.getCityId())
                .build();
        Integer servItemType = this.getServItemType(checkQuotationTypeOrderDTO);

        return getService(servItemType).queryBackProductPrice(backProductPriceQueryDTO);
    }

    @Override
    public void checkOrderWorkServItemType(CheckOrderServItemTypeDTO dto) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(dto.getOrderId(), dto.getWorkId());
        // 前端传过来的type和数据库中的type比较
        if (!Objects.equals(dto.getServItemType(), orderWork.getServItemType())) {
            throw new OmsBaseException("订单类型已变更，请刷新后再试");
        }

        Integer oriServItemType = orderWork.getServItemType();
        Integer oriFinalPrice = orderWork.getFinalPrice();
        if (Objects.equals(oriFinalPrice, GlobalConsts.YES)) {
            oriServItemType = OrderConsts.SERVICE_ITEM_TYPE_FINAL_PRICE;
        }

        // 数据库的type和配置比较
        CheckQuotationTypeOrderDTO checkQuotationTypeOrderDTO = CheckQuotationTypeOrderDTO.builder()
                .type(orderWork.getType())
                .platWork(orderWork.getPlatWork())
                .productId(orderWork.getProductId())
                .showProductId(orderWork.getShowProductId())
                .cityId(orderWork.getCityId())
                .channelId(orderWork.getChannelId())
                .bizType(orderWork.getBizType())
                .masterId(orderWork.getMasterId())
                .companyId(orderWork.getCompanyId())
                .beforeServItemType(orderWork.getServItemType())
                .build();
        Integer servItemType = this.getServItemType(checkQuotationTypeOrderDTO);

        if (!Objects.equals(oriServItemType, servItemType)) {
            OrderWork updateOrderWork = new OrderWork();
            updateOrderWork.setOrderId(dto.getOrderId());
            updateOrderWork.setWorkId(dto.getWorkId());
            // servItemType==5的修改成4，并且标识一口价（一口价订单需求兼容app走计价器3.0流程）
            if (Objects.equals(servItemType, OrderConsts.SERVICE_ITEM_TYPE_FINAL_PRICE)) {
                updateOrderWork.setServItemType(OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE);
                updateOrderWork.setFinalPrice(GlobalConsts.YES);
            }else {
                updateOrderWork.setServItemType(servItemType);
                updateOrderWork.setFinalPrice(GlobalConsts.NO);
            }
            log.info("[{}]修改计价类型，旧类型[{},{}]-->新类型[{},{}]", orderWork.getWorkId(), orderWork.getServItemType(), orderWork.getFinalPrice(), updateOrderWork.getServItemType(), updateOrderWork.getFinalPrice());
            orderWorkService.updateOrderServItemTypeByKey(updateOrderWork);

            List<OrderProduct> orderProductList = orderProductService.listOrderProductByOrderId(dto.getOrderId());
            orderProductList.forEach(e->{
                e.setTariffId(null);
            });
            ProductTaraiffIdDTO productTaraiffIdDTO = ProductTaraiffIdDTO.builder()
                    .orderProductList(orderProductList)
                    .cityId(orderWork.getCityId())
                    .bizType(orderWork.getBizType())
                    .channelId(orderWork.getChannelId())
                    .tariffType(servItemType)
                    .build();
            this.processProductTaraiffId(productTaraiffIdDTO);
            orderProductService.updateTariffIdByKey(orderProductList.get(0));

            // 保存新的servItemType到进行中工单表
            MasterWorking updateMasterWorking = new MasterWorking();
            updateMasterWorking.setWorkId(orderWork.getWorkId());
            updateMasterWorking.setServItemType(updateOrderWork.getServItemType());
            updateMasterWorking.setFinalPrice(updateOrderWork.getFinalPrice());
            masterWorkingService.updateMasterWorking(updateMasterWorking);

            throw new OmsBaseException("订单类型已变更，请刷新后再试");
        }
    }

    private Map<Integer, ProductBaseDRO> getProductBaseDROMap(List<Integer> productIds) throws OmsBaseException {
        ProductBaseQuery productBaseQuery = ProductBaseQuery
                .builder()
                .productIdList(productIds)
                .build();
        log.info("productForeignListRemoteService.listBaseDROByQuery productBaseQuery={}", productBaseQuery);
        ResponseDTO<List<ProductBaseDRO>> productResponseDTO = productForeignListRemoteService.listBaseDROByQuery(productBaseQuery);
        log.info("productForeignListRemoteService.listBaseDROByQuery productResponseDTO={}", productResponseDTO);
        if (!productResponseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(productResponseDTO.getData())) {
            throw new OmsBaseException(String.format("产品不存在，productIds=[%s]", JSON.toJSONString(productIds)));
        }
        return Maps.uniqueIndex(productResponseDTO.getData(), ProductBaseDRO::getProductId);
    }

    @Override
    public void verifyServiceItem(List<OrderServiceItem> orderServiceItemList) throws OmsBaseException {
        if (CollectionUtil.isNullOrEmpty(orderServiceItemList)) {
            return;
        }
        List<Integer> itemAdditionServItemIdList = orderServiceItemList.stream()
                .filter(e -> Objects.equals(e.getServItemGroupId(), ServiceItemTypeEnum.ADDITION_ITEM.getType()))
                .map(OrderServiceItem::getServItemId)
                .collect(Collectors.toList());

        if (CollectionUtil.isNullOrEmpty(itemAdditionServItemIdList)) {
            return;
        }

        // 附加项
        log.info("查询附加项#itemAdditionRemoteService.listByIds ids={}", itemAdditionServItemIdList);
        ResponseDTO<List<ItemAdditionDRO>> listResponseDTO = itemAdditionRemoteService.listByIds(itemAdditionServItemIdList);
        log.info("查询附加项#itemAdditionRemoteService.listByIds listResponseDTO={}", listResponseDTO);
        if (CollectionUtil.isNullOrEmpty(listResponseDTO.getData())) {
            return;
        }
        Date now = DateUtil.getNow();
        Integer nowTime = Integer.parseInt(DateUtil.toString(now, "HHmmss"));
        for (ItemAdditionDRO itemAdditionDRO : listResponseDTO.getData()) {
            if (Objects.isNull(itemAdditionDRO.getBeginTime())) {
                continue;
            }
            if (Objects.isNull(itemAdditionDRO.getEndTime())) {
                continue;
            }
            Integer beginTime = Integer.parseInt(DateUtil.toString(itemAdditionDRO.getBeginTime(), "HHmmss"));
            Integer endTime = Integer.parseInt(DateUtil.toString(itemAdditionDRO.getEndTime(), "HHmmss"));

            if (!(nowTime >= beginTime && nowTime <= endTime)) {
                throw new OmsBaseException(
                        String.format("当前时间不能选择此服务项[%s],允许选择时间：%s~%s",
                                itemAdditionDRO.getItemAdditionName(),
                                DateUtil.toString(itemAdditionDRO.getBeginTime(), "HH:mm:ss"),
                                DateUtil.toString(itemAdditionDRO.getEndTime(), "HH:mm:ss"))
                );
            }
        }
    }

    @Override
    public List<Integer> getServItemTypeIdList(Integer servItemType) {
        log.info("getServItemTypeIdList servItemType={}", servItemType);
        return getService(servItemType).getServItemTypeIdList(servItemType);
    }

    @Override
    public List<ArtificialPromDRO> listArtificialProm(Integer servItemType, ArtificialPromQueryDTO query) throws OmsBaseException {
        log.info("listArtificialProm servItemType={},query={}", servItemType, query);
        return getService(servItemType).listArtificialProm(servItemType, query);
    }
}
